import groovy.mock.interceptor.MockFor
import net.yiny.scrummer.model.Card
import net.yiny.scrummer.model.PhaseStrip
import net.yiny.scrummer.ui.storyboard.CardControllerFactory
import net.yiny.scrummer.ui.storyboard.PhaseStripBuilder
import net.yiny.scrummer.ui.storyboard.PhaseStripControllerFactory

before_each "setup a factory", {
    factory = new PhaseStripControllerFactory()
    cardFactory = new CardControllerFactory()
}

scenario "creating a controller for a phase strip with no cards in it", {
    given "a phase strip that has no cards in it", {
        phaseStrip = new PhaseStrip()
    }
    when "the factory is asked to create a controller", {
        controller = factory.createController(phaseStrip, cardFactory)
    }
    then 'the controller created should have no children', {
        controller.shouldNotBe null
        and
        controller.children.shouldBe[]
    }
    then 'the builder should not be null and have no children', {
        controller.builder.shouldNotBe null
        and
        controller.builder.children.shouldBe[]
    }
    then 'the phase strip should be the same one we gave it to create for', {
        controller.phaseStrip.shouldBe phaseStrip
    }
}

scenario 'creating a controller for a phase strip with one card in it', {
    given 'a phase strip with one card in it', {
        card = new Card()
        phaseStrip = new PhaseStrip(cards: [card])
    }
    when 'the factory is asked to create a controller', {
        controller = factory.createController(phaseStrip, cardFactory)
    }
    then 'the controller created should have one child', {
        controller.shouldNotBe null
        and
        controller.children.size.shouldBe 1
    }
    then 'the child controller should have the card', {
        controller.children[0].card.shouldBe card
    }
    then 'the builder should have one child builder', {
        controller.builder.children.size.shouldBe 1
    }
    then 'the phase strip should be the same one we gave it to create for', {
        controller.phaseStrip.shouldBe phaseStrip
    }
}

scenario 'creating a controller for a phase strip with two cards in it', {
    given 'a phase strip with two cards in it', {
        cards = [new Card(), new Card()]
        phaseStrip = new PhaseStrip(cards: cards)
    }
    when 'the factory is asked to create a controller', {
        controller = factory.createController(phaseStrip, cardFactory)
    }
    then 'the controller created should have two children', {
        controller.shouldNotBe null
        and
        controller.children.size.shouldBe cards.size
    }
    then 'the child controllers should have the cards', {
        controller.children*.card.shouldBe cards
    }
    then 'the builder should have two children', {
        controller.builder.children.size.shouldBe cards.size
    }
    then 'the phase strip should be the same one we gave in creation', {
        controller.phaseStrip.shouldBe phaseStrip
    }
}

scenario 'passing in a null phase strip', {
    when 'the factory is asked to create a controller but passed a null phase strip', {
        wasThrown = true
        ensureThrows(IllegalArgumentException) {
            controller = factory.createController(null, cardFactory)
            wasThrown = false
        }
    }
    then 'an illegal argument exception should have been thrown', {
        wasThrown.shouldBe true
    }
}

scenario 'passing in a null card factory', {
    when 'the factory is asked to create a controller but passed a null card factory', {
        wasThrown = true
        ensureThrows(IllegalArgumentException) {
            controller = factory.createController(new PhaseStrip(), null)
            wasThrown = false
        }
    }
    then 'an illegal argument exception should have been thrown', {
        wasThrown.shouldBe true
    }
}

scenario 'making the controller observe builder notifications', {
    given 'a phase strip with no cards in it', {
        phaseStrip = new PhaseStrip()
    }
    when 'we create a controller for it through the factory', {
        listener = null
        mockBuilderClass = new MockFor(PhaseStripBuilder)
        mockBuilderClass.demand.addListener {listener = it}
        mockBuilderClass.use {
            controller = factory.createController(new PhaseStrip(), cardFactory)
        }
    }
    then 'the controller adds itself to the listeners of the builder', {
        listener.shouldBeEqualTo controller
    }
}

scenario 'adding a card to an existing phase strip controller', {
    PhaseStrip emptyPhaseStrip = new PhaseStrip()
    given 'a phase strip controller that has already been setup, and a new card', {
        controller = factory.createController(emptyPhaseStrip, cardFactory)
        card = new Card()
    }
    when 'we ask the factory to add a card to the controller', {
        factory.addCard(controller, cardFactory, card)
    }
    then 'the controller should have one child with the same card as we added', {
        controller.children.card.shouldBe([card])
    }
    and 'the controller\'s builder should have one child builder', {
        controller.builder.children.size.shouldBe 1
    }
    and 'the phase strip should still be the same one we gave in creation', {
        controller.phaseStrip.shouldBe emptyPhaseStrip
    }
}
